#pragma once
#include"MyString.h"


const size_t MyString::npos = -1;
//MyString::MyString()
//	:_str(new char[1] {'\0'})
//	, _size(0)
//	, _capacity(0)
//{}

MyString::MyString(const char* str)
	:_size(strlen(str))
	, _capacity(_size)
{
	_str = new char[_capacity + 1];
	strcpy(_str, str);
}

void MyString::swap(MyString& s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

// s2(s1)
MyString::MyString(const MyString& s)
	:_str(nullptr)
	, _size(0)
	, _capacity(0)
{
	cout << "string(const string& s) -- 深拷贝" << endl;
	MyString tmp(s._str);
	swap(tmp);
}

// s2 = s3
MyString& MyString::operator=(MyString tmp)
{
	cout << "string& operator=(const string& s) -- 深拷贝" << endl;
	swap(tmp);
	return *this;
}

MyString::~MyString()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

char& MyString::operator[](size_t pos)
{
	assert(pos < _size);

	return _str[pos];
}

const char& MyString::operator[](size_t pos) const
{
	assert(pos < _size);
	return _str[pos];
}

size_t MyString::capacity() const
{
	return _capacity;
}

size_t MyString::size() const
{
	return _size;
}

const char* MyString::c_str() const
{
	return _str;
}

void MyString::reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;

		_capacity = n;
	}
}

void MyString::resize(size_t n, char ch)
{
	if (n <= _size)
	{
		_str[n] = '\0';
		_size = n;
	}
	else
	{
		reserve(n);
		while (_size < n)
		{
			_str[_size] = ch;
			++_size;
		}

		_str[_size] = '\0';
	}
}

size_t MyString::find(char ch, size_t pos)
{
	for (size_t i = pos; i < _size; i++)
	{
		if (_str[i] == ch)
		{
			return i;
		}
	}

	return npos;
}

size_t MyString::find(const char* sub, size_t pos)
{
	const char* p = strstr(_str + pos, sub);
	if (p)
	{
		return p - _str;
	}
	else
	{
		return npos;
	}
}

MyString MyString::substr(size_t pos, size_t len)
{
	MyString s;
	size_t end = pos + len;
	if (len == npos || pos + len >= _size) // 有多少取多少
	{
		len = _size - len;
		end = _size;
	}

	s.reserve(len);
	for (size_t i = pos; i < end; i++)
	{
		s += _str[i];
	}

	return s;
}

void MyString::push_back(char ch)
{
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}

	_str[_size] = ch;
	++_size;
	_str[_size] = '\0';
}

void MyString::append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}

	strcpy(_str + _size, str);
	_size += len;
}

MyString& MyString::operator+=(char ch)
{
	push_back(ch);
	return *this;
}

MyString& MyString::operator+=(const char* str)
{
	append(str);
	return *this;
}

// insert(0, 'x')
void MyString::insert(size_t pos, char ch)
{
	assert(pos <= _size);
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}

	size_t end = _size + 1;
	while (end > pos)
	{
		_str[end] = _str[end - 1];
		--end;
	}

	_str[pos] = ch;
	_size++;
}

void MyString::insert(size_t pos, const char* str)
{
	assert(pos <= _size);

	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}

	// 挪动数据
	int end = _size;
	while (end >= (int)pos)
	{
		_str[end + len] = _str[end];
		--end;
	}

	strncpy(_str + pos, str, len);
	_size += len;
}

void MyString::erase(size_t pos, size_t len)
{
	assert(pos < _size);

	if (len == npos || pos + len >= _size)
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		size_t begin = pos + len;
		while (begin <= _size)
		{
			_str[begin - len] = _str[begin];
			++begin;
		}
		_size -= len;
	}
}

bool MyString::operator<(const MyString& s) const
{
	return strcmp(_str, s._str) < 0;
}

bool MyString::operator==(const MyString& s) const
{
	return strcmp(_str, s._str) == 0;
}

bool MyString::operator<=(const MyString& s) const
{
	return *this < s || *this == s;
}

bool MyString::operator>(const MyString& s) const
{
	return !(*this <= s);
}

bool MyString::operator>=(const MyString& s) const
{
	return !(*this < s);
}

bool MyString::operator!=(const MyString& s) const
{
	return !(*this == s);
}

void MyString::clear()
{
	_str[0] = '\0';
	_size = 0;
}

std::ostream& operator<<(std::ostream& out, const MyString& s)
{
	for (auto ch : s)
		out << ch;

	return out;
}

std::istream& operator>>(std::istream& in, MyString& s)
{

	s.clear();

	char buff[129];
	size_t i = 0;

	char ch;
	ch = in.get();
	while (ch != ' ' && ch != '\n')
	{
		buff[i++] = ch;
		if (i == 128)
		{
			buff[i] = '\0';
			s += buff;
			i = 0;
		}

		//s += ch;

		ch = in.get();
	}

	if (i != 0)
	{
		buff[i] = '\0';
		s += buff;
	}

	return in;
}


MyString to_string(int value)
{
	MyString ret;

	while (value > 0)
	{
		int x = value % 10;
		value /= 10;
		ret += ('0' + x);
	}
	
	return ret;
}